﻿#include "access.h"
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>

Access::Access(QList<IPC *> &ipcList, QString &url, QString &id, QString &faceEnterUrl, QObject *parent) :
    QObject(parent),
    m_ws(),
    m_faceEnterManager(),
    m_faceUrl(faceEnterUrl),
    m_url(url),
    m_id(id),
    m_ipcList(ipcList),
    m_heartbeatTimer()
{
    DEBUG_PRINT << m_url << m_id;
    m_faceEnterManager.setCookieJar(Q_NULLPTR);
    connect(&m_ws, SIGNAL(connected()), this, SLOT(onConnected()));
    connect(&m_ws, SIGNAL(textMessageReceived(QString)), this, SLOT(onTextMessageReceived(QString)));
    connect(&m_ws, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onError(QAbstractSocket::SocketError)));
    connect(&m_heartbeatTimer, SIGNAL(timeout()), this, SLOT(onHeartbeatTimeout()));
    connect(&m_faceEnterManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFaceEnterFinished(QNetworkReply*)));
    m_ws.open(QUrl(m_url));
    m_heartbeatTimer.start(1000);
}

Access::~Access()
{
    m_ws.disconnect();
    m_ws.close();
}

void Access::onConnected()
{
    DEBUG_PRINT << "onConnected";

    QJsonObject jsonLogin;
    jsonLogin.insert("cmd_version", "1.0");
    jsonLogin.insert("data_type", 0);
    jsonLogin.insert("client_type", 0);
    jsonLogin.insert("client_version", "0.1");
    jsonLogin.insert("client_id", m_id);
    jsonLogin.insert("length", QJsonDocument(jsonLogin).toJson(QJsonDocument::Compact).size() - 2);
    jsonLogin.insert("type", 1);
    m_ws.sendTextMessage(QJsonDocument(jsonLogin).toJson(QJsonDocument::Compact));
}

void Access::onHeartbeatTimeout()
{
    if (m_ws.state() == QAbstractSocket::UnconnectedState)
    {
        DEBUG_PRINT << "access unconnected";
        m_ws.open(QUrl(m_url));
        return ;
    }
    else if (m_ws.state() != QAbstractSocket::ConnectedState)
    {
        return ;
    }

    QJsonObject jsonHeartbeat;
    jsonHeartbeat.insert("type", 2);
    jsonHeartbeat.insert("length", 0);
    m_ws.sendTextMessage(QJsonDocument(jsonHeartbeat).toJson(QJsonDocument::Compact));

    QJsonArray ipcList;
    foreach (IPC *ipc, m_ipcList)
    {
        if (ipc->m_devState)
        {
            QJsonObject ipcId;
            ipcId.insert("ipc_id", ipc->m_id);
            ipcList.append(ipcId);
        }
    }

    QJsonObject jsonStatus;
    jsonStatus.insert("cmd", 0x02000002);
    jsonStatus.insert("proxy_id", m_id);
    jsonStatus.insert("ipc_num", ipcList.size());
    jsonStatus.insert("ipc_list", ipcList);
    jsonStatus.insert("length", QJsonDocument(jsonStatus).toJson(QJsonDocument::Compact).size() - 2);
    jsonStatus.insert("type", 5);
    m_ws.sendTextMessage(QJsonDocument(jsonStatus).toJson(QJsonDocument::Compact));
}

void Access::onTextMessageReceived(QString recv)
{
    emit this->textRecv(recv);
    QJsonParseError jsonErr;
    QJsonObject jsonObj;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(recv.toLatin1(), &jsonErr);

    if (jsonErr.error != QJsonParseError::NoError && !jsonDoc.isObject())
    {
        WARNING_PRINT << "recv unkown msg" << recv;
        return ;
    }

    jsonObj = jsonDoc.object();

    switch (jsonObj["type"].toInt())
    {
    case 1:
        if (jsonObj["code"].toInt() == 200)
        {
            onHeartbeatTimeout();
            m_heartbeatTimer.start(jsonObj["heartbeat"].toInt() * 1000);
        }
        break;
    case 2:
        break;
    case 3:
        switch (jsonObj["cmd"].toInt())
        {
        case 0x3000001:
        {
            QString id = jsonObj["stream_id"].toString();
            QString ip = jsonObj["sms_ip"].toString();
            int port = jsonObj["sms_port"].toInt();

            foreach (IPC *ipc, m_ipcList)
            {
                QString tmp = id.mid(id.indexOf('_') + 1);
                if (ipc->m_id == tmp.mid(0, tmp.indexOf('_')))
                {
                    ipc->startSMS(ip, port, id);
                }
            }
        }
            break;
        case 0x3000002:
            //处理完全一样，不break
        case 0x3000003:
        {
            m_faceEnterManager.clearAccessCache();
            if (m_faceEnterManager.children().size() > 0)
            {
                m_faceEnterManager.children().first()->deleteLater();
            }
            QNetworkRequest req;
            req.setUrl(QUrl(m_faceUrl));
            req.setHeader(QNetworkRequest::ContentTypeHeader, " ");
            m_faceEnterManager.post(req, recv.toLatin1());
        }
            break;
        default:
            break;
        }
        break;
    case 5:
        if (jsonObj["result_code"].toInt() != 0)
        {
            WARNING_PRINT << jsonObj["result_reason"].toString();
        }
        break;
    default:
        break;
    }
}

void Access::onError(QAbstractSocket::SocketError err)
{
    WARNING_PRINT << err;
    m_heartbeatTimer.start(1000);
}

void Access::onFaceEnterFinished(QNetworkReply *r)
{
    QByteArray data = r->readAll();
    DEBUG_PRINT << data;
    Q_UNUSED(data);
    r->deleteLater();
}
